﻿using System;

namespace HashFoo.Rest.Common
{
    /// <summary>
    /// Creates a <see cref="IDispatcher"/> based on a set of function callbacks.  Useful for not having do define a specific class for
    /// all types of dispatchers.
    /// </summary>
    public class FuncDispatcher : IDispatcher
    {
        /// <summary>
        /// Creates the defualt dispatcher with default function that execute on the current UI thread.
        /// Set <see cref="AsynInvoker"/> and <see cref="RequiresInvokeChecker"/> for custom behavior.
        /// </summary>
        public FuncDispatcher( )
        {
            AsynInvoker = (x => x.BeginInvoke(null, null));
            RequiresInvokeChecker = (() => false);
        }

        /// <summary>
        /// The async dispatch invoker action.
        /// </summary>
        public Action<Action> AsynInvoker { get; set; }

        /// <summary>
        /// Function that checks if an invoke is required.
        /// </summary>
        public Func<bool> RequiresInvokeChecker { get; set; }

        /// <summary>
        /// Dispatch a worker onto the UI thread.
        /// </summary>
        /// <param name="worker">The worker to execute.</param>
        /// <param name="force">If true, forces the call to be invoked, else: invokes if <see cref="IDispatcher.RequiresInvoke"/> is true, else executes the worker on the current thread.</param>
        public void BeginInvoke(Action worker, bool force = false)
        {
            if (force  || RequiresInvoke) AsynInvoker(worker);
            else worker.BeginInvoke(null, null);
        }

        /// <summary>
        /// True if an invoke is needed to get back the dispatchers source thread (the UI thread).
        /// </summary>
        public bool RequiresInvoke
        {
            get { return RequiresInvokeChecker(); }
        }
    }
}